/* test_mutex_func_uthread_mutex_try_lock():
	A test for uthread_mutex_try_lock(). Checks the regular case + the error
	cases.

	Does:
	* Creates additional thread: 1.

	1)
	* Checks for MUTEX_INVALID error.
	* Checks for MUTEX_UNINITIALIZED error.

	2)
	* thread 0 try-locks mutex_a twise.
	* thread 1 try-locks mutex_a (MUTEX_LOCKED).
	* thread 0 unlocks mutex_a twise.
	* thread 1 try-locks mutex_a (success).

*/


#include <stdio.h>
#include <stdbool.h>

#include "test_general.h"
#include "user_threads.h"
#include "user_mutex.h"


bool test_mutex_func_uthread_mutex_try_lock();


#define THREADS_NUM 2


uthread_mutex_t mutex_a;


static int thread1_start_routine(void * param) {
	TEST_ASSERT (uthread_self() == 1);

	some_long_operation(0.1);

	int tmp = uthread_mutex_try_lock(mutex_a);
	TEST_ASSERT(MUTEX_LOCKED == tmp);

	some_long_operation(0.2);
	// thread 0 unlocked mutex_a.

	tmp = uthread_mutex_try_lock(mutex_a);
	TEST_ASSERT(MUTEX_SUCCESS == tmp);

	tmp = uthread_mutex_unlock(mutex_a);
	TEST_ASSERT(tmp == MUTEX_SUCCESS);

	tmp = uthread_mutex_destroy(mutex_a);
	TEST_ASSERT(tmp == MUTEX_SUCCESS);

	thread_ok[1] = true;
	return 0;
}


bool test_mutex_func_uthread_mutex_try_lock()
{
	init_individual_test();

	int tmp;

	/*if (initilize_uthread_in_each_test) {
		tmp = uthread_init();
		TEST_ASSERT(tmp == UTHREAD_SUCCESS);
	}*/


	/* Checking for MUTEX_INVALID,MUTEX_UNINITIALIZED: */
	tmp = uthread_mutex_try_lock(NULL);
	TEST_ASSERT (MUTEX_INVALID == tmp);
	tmp = uthread_mutex_try_lock((uthread_mutex_t)&tmp);
	TEST_ASSERT (MUTEX_UNINITIALIZED == tmp);


	tmp = uthread_mutex_init(&mutex_a);
	TEST_ASSERT(tmp == MUTEX_SUCCESS);

	uthread_id threads[THREADS_NUM];

	threads[0] = uthread_self();
	TEST_ASSERT(threads[0] == 0);

	int FiftyThree = 53;

	threads[1] = uthread_create(thread1_start_routine, &FiftyThree);
	TEST_ASSERT(threads[1] == 1);


	tmp = uthread_mutex_try_lock(mutex_a);
	TEST_ASSERT(tmp == MUTEX_SUCCESS);
	/*tmp = uthread_mutex_try_lock(mutex_a);
	TEST_ASSERT(tmp == MUTEX_SUCCESS);  --  WE can not lock the sam mutex twice. */
	tmp = uthread_mutex_try_lock(mutex_a);
	TEST_ASSERT(tmp == MUTEX_LOCKED);  

	some_long_operation(0.1);
	some_long_operation(0.1);

	tmp = uthread_mutex_unlock(mutex_a);
	TEST_ASSERT(tmp == MUTEX_SUCCESS);
	/*tmp = uthread_mutex_unlock(mutex_a);
	TEST_ASSERT(tmp == MUTEX_SUCCESS); */
	tmp = uthread_mutex_unlock(mutex_a);
	TEST_ASSERT(tmp == MUTEX_UNLOCKED); 

	tmp = uthread_join(1,NULL);
	TEST_ASSERT(tmp == UTHREAD_SUCCESS);


	thread_ok[0] = true;
	TEST_ASSERT(are_all_threads_ok(THREADS_NUM));

	return true;
}

